﻿using System;

namespace RexToy.UI.Controls
{
    public class GridPanel : Container
    {
        private uint __columns;
        public uint Columns
        {
            get { return __columns; }
        }

        private uint __rows;
        public uint Rows
        {
            get { return __rows; }
        }

        private Control[][] _cellctrls;

        public GridPanel(uint rows, uint columns)
        {
            __sizeUpdate = true;
            var arr = new string[] { "a", "b", "c", "d", "e" };
            if (columns < 2 || columns > 5)
                throw new RangeError("valid value is 2 <= cols <= 5");
            this.__columns = columns;
            this.__rows = rows;
            var hostClass = StringExt.Format("ui-grid-{0}", arr[columns - 2]);
            this.__domNode = RexToy.UI.Controls.DomNode.Create(new DomNodeCreateOptions()
            {
                tag = Tag.Div,
                hashName = "host",
                className = hostClass
            });

            for (var r = 0; r < rows; r++)
            {
                for (var i = 0; i < columns; i++)
                {
                    var childClass = StringExt.Format("ui-block-{0}", arr[i]);
                    var child = RexToy.UI.Controls.DomNode.Create(new DomNodeCreateOptions()
                    {
                        tag = Tag.Div,
                        className = childClass
                    });
                    this.__domNode.AppendChild(child);
                }
            }

            this._cellctrls = new Control[][] { };
            for (var i = 0; i < this.__rows; i++)
            {
                for (var j = 0; j < this.__columns; j++)
                {
                    this._cellctrls.Push(new Control[0]);
                }
            }
        }

        public void AppendControl(uint row, uint col, Control ctrl)
        {
            if (col < 0 || col >= this.__columns)
                throw new RangeError("col not valid");
            if (row < 0 || row >= this.__rows)
                throw new RangeError("row not valid");

            ctrl.Init();
            this.__domNode.GetChildren()[row * this.__columns + col].AppendChild(ctrl.DomNode);
            this._cellctrls[row * this.__columns + col].Push(ctrl);
        }

        public void RemoveControl(uint row, uint col, Control ctrl)
        {
            if (col < 0 || col >= this.__columns)
                throw new RangeError("col not valid");
            if (row < 0 || row >= this.__rows)
                throw new RangeError("row not valid");

            this.__domNode.GetChildren()[row * this.__columns + col].RemoveChild(ctrl.DomNode);
            this._cellctrls[row * this.__columns + col].Remove(ctrl);
        }

        public void InsertControlAt(uint row, uint col, Control ctrl, uint idx)
        {
            if (col < 0 || col >= this.__columns)
                throw new RangeError("col not valid");
            if (row < 0 || row >= this.__rows)
                throw new RangeError("row not valid");

            this.__domNode.GetChildren()[row * this.__columns + col].InsertChildAt(ctrl.DomNode, idx);
            this._cellctrls[row * this.__columns + col].InsertAt(ctrl, idx);
        }

        public override void ClearControls()
        {
            for (var i = 0; i < this.__rows; i++)
            {
                for (var j = 0; j < this.__columns; j++)
                {
                    var dom = this.__domNode.GetChildren()[i * this.__columns + j];
                    var arr = this._cellctrls[i * this.__columns + j];
                    for (var k = 0; k < arr.Length; k++)
                    {
                        dom.RemoveChild(arr[k].DomNode);
                    }
                    this._cellctrls[i * this.__columns + j] = new Control[0];
                }
            }
        }

        public override void Render(Size size)
        {
            int rowHeight = (int)(size.Height / this.__rows);

            for (var i = 0; i < this.__rows; i++)
            {
                for (var j = 0; j < this.__columns; j++)
                {
                    var container = this.__domNode.GetChildren()[i * this.__columns + j];
                    container.Height = rowHeight;

                    var h = rowHeight;
                    Control resizeCtrl = null;
                    for (var k = 0; k < this._cellctrls[i * this.__columns + j].Length; k++)
                    {
                        var ctrl = this._cellctrls[i * this.__columns + j][k];
                        var ctn = ctrl as Container;
                        if (ctrl.IsContainer && ctn.SizeUpdate)
                        {
                            if (resizeCtrl != null)
                                throw new Exception("container can have only 1 resizable control!");
                            else
                                resizeCtrl = ctrl;
                        }
                        else
                        {
                            h -= ctrl.GetSize().Height;
                            if (ctrl.IsContainer)
                                ctrl.Render(ctrl.GetSize());
                        }
                    }
                    if (resizeCtrl != null)
                    {
                        resizeCtrl.DomNode.Height = h;
                        resizeCtrl.Render(new RexToy.UI.Size(container.Width, h));
                    }
                }
            }
        }
    }
}
